package com.liuyjy.utils.utils;

import com.liuyjy.core.constant.CharacterConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Author liuyjy
 * @Date 2022/3/3 15:32
 * @Description: 对象非空判断
 **/
@Slf4j
public class EmptyUtil {
    /**
     * 判断Object是否不为空,先判断是否不为null，为null返回false;不为null 继续判断toString()是否不为空
     */
    public static <T> boolean isNotEmpty(T value) {
        return !isEmpty(value);
    }

    /**
     * 判断list是否不为空
     */
    public static <T> boolean isNotEmpty(List<T> lists) {
        return !isEmpty(lists);
    }

    /**
     * 判断set是否不为空
     */
    public static <T> boolean isNotEmpty(Set<T> tSet) {
        return !isEmpty(tSet);
    }

    /**
     * 判断Collection是否不为空
     */
    public static <T> boolean isNotEmpty(Collection<T> collection) {
        return !isEmpty(collection);
    }

    /**
     * 判断数组是否不为空
     */
    public static <T> boolean isNotEmpty(T[] datas) {
        return !isEmpty(datas);
    }

    /**
     * 判断字符串是否不为空
     */
    public static boolean isNotEmpty(String datas) {
        return !isEmpty(datas);
    }

    /**
     * 判断Map是否不为空
     */
    @SuppressWarnings("rawtypes")
    public static boolean isNotEmpty(Map datas) {
        return !isEmpty(datas);
    }

    /**
     * 判断一个对象的所有字段是否都为空
     * 通过反射遍历对象的所有字段，并检查它们的值是否为空
     * 主要用于在不直接访问对象的属性的情况下，统一判断对象的空状态
     *
     * @param obj 要检查的对象
     * @return 如果所有字段都为空，则返回true；否则返回false
     */
    public static boolean objectIsNotEmpty(Object obj) {
        return !objectIsEmpty(obj);
    }


    /**
     * 判断字符串不能为空，且不能为“undefined”，主要是在js选择后验证，可以调用此方法
     */
    public static boolean isNotUndefinedChars(String value) {
        return !isUndefinedChars(value);
    }

    /**
     * 判断字符串不能为空，且不能为“null”，主要是在js选择后验证，可以调用此方法
     */
    public static boolean isNotNullChars(String value) {
        return !isNullChars(value);
    }

    /**
     * 判断字符串不能为空，且不能为“null”和“undefined”，主要是在js选择后验证，可以调用此方法
     */
    public static boolean isNotEmptyChars(String value) {
        return !isEmptyChars(value);
    }

    /**
     * 判断list是否为空
     */
    public static <T> boolean isEmpty(List<T> lists) {
        return isNull(lists) || lists.isEmpty();
    }

    /**
     * 判断set是否为空
     */
    public static <T> boolean isEmpty(Set<T> tSet) {
        return isNull(tSet) || tSet.isEmpty();
    }

    /**
     * 判断Collection是否为空
     */
    public static <T> boolean isEmpty(Collection<T> collection) {
        return isNull(collection) || collection.isEmpty();
    }

    /**
     * 判断数组是否为空
     */
    public static <T> boolean isEmpty(T[] datas) {
        return isNull(datas) || datas.length == 0;
    }

    /**
     * 判断字符串是否为空
     */
    public static boolean isEmpty(String datas) {
        return StringUtils.isBlank(datas) || datas.trim().isEmpty();
    }

    /**
     * 判断Map是否为空
     */
    @SuppressWarnings("rawtypes")
    public static boolean isEmpty(Map datas) {
        return datas == null || datas.isEmpty();
    }

    /**
     * 判断字符串为空，或为“undefined”，主要是在js选择后验证，可以调用此方法
     */
    public static boolean isUndefinedChars(String value) {
        if (isEmpty(value)) {
            return true;
        }
        return CharacterConstant.UNDEFINED.equalsIgnoreCase(value.trim());
    }

    /**
     * 判断字符串为空，或为“null”，主要是在js选择后验证，可以调用此方法
     */
    public static boolean isNullChars(String value) {
        if (isEmpty(value)) {
            return true;
        }
        return CharacterConstant.NULL.equalsIgnoreCase(value.trim());
    }

    /**
     * 判断字符串为空，或为“null”和“undefined”，主要是在js选择后验证，可以调用此方法
     */
    public static boolean isEmptyChars(String value) {
        return isNullChars(value) || isUndefinedChars(value);
    }

    /**
     * 判断Object是否不为空,先判断是否不为null，为null返回false;不为null 继续判断toString()是否不为空
     */
    public static <T> boolean isEmpty(T value) {
        return isNull(value);
    }

    /**
     * 判断一个对象的所有字段是否都为空
     * 通过反射遍历对象的所有字段，并检查它们的值是否为空
     * 主要用于在不直接访问对象的属性的情况下，统一判断对象的空状态
     *
     * @param obj 要检查的对象
     * @return 如果所有字段都为空，则返回true；否则返回false
     */
    public static boolean objectIsEmpty(Object obj) {
        if (isEmpty(obj)) {
            return true;
        }
        try {
            // 遍历对象的所有字段
            for (Field field : ReflectUtil.getAllFields(obj)) {
                // 把私有属性公有化，以便能够访问它们
                field.setAccessible(true);
                // 获取字段的值
                Object value = field.get(obj);
                // 如果字段值不为空，则返回false
                if (EmptyUtil.isNotEmpty(value)) {
                    return false;
                }
            }
        } catch (Exception e) {
            // 打印异常信息，但不处理异常，因为异常处理可能会影响性能
            log.error("allFieldIsEmpty方法发生异常", e);
            // e.printStackTrace();

        }
        return true;
    }

    /**
     * 判断参数obj是否为null，如果obj为null,返回false；不为null，返回true
     */
    public static boolean isNotNull(Object obj) {
        return !isNull(obj);
    }

    /**
     * 判断参数obj是否为null，如果obj为null,返回true；不为null，返回false
     */
    public static boolean isNull(Object obj) {
        return null == obj;
    }
}
